package jmine.tec.web.wicket.pages.form;

import static jmine.tec.web.wicket.component.breadcrumb.BreadcrumbPanel.BREAD_CRUMB_SEPARATOR;

import java.util.List;

import jmine.tec.web.wicket.component.MapsWicketDateTextField;
import jmine.tec.web.wicket.pages.Template;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;

import bancosys.tec.utils.date.Date;

/**
 * Página base para a criação de páginas que possuem formulários.
 * 
 * @author Rafael Volpato
 * @date Aug 8, 2011
 */
public abstract class AbstractFormPage extends Template {

    /**
     * Construtor.
     */
    public AbstractFormPage() {
        super();
    }

    /**
     * Construtor
     * 
     * @param pageParameters {@link PageParameters}
     */
    public AbstractFormPage(PageParameters pageParameters) {
        super(pageParameters);
    }

    /**
     * O nome da página.
     * 
     * @return O nome da página
     */
    protected String getPageName() {
        String[] breadCrumb = this.getPagePath();
        if ((breadCrumb != null) && (breadCrumb.length > 0)) {
            return breadCrumb[breadCrumb.length - 1];
        } else {
            return "";
        }
    }

    /**
     * Retorna o path da página.
     * 
     * @return o path da página.
     */
    private String[] getPagePath() {
        return this.getMenuPanel().getPagePath(this.getClass());
    }

    /**
     * Retorna o nome completo da página da mesma forma que é exibido no breadcrumb com o separador " - "
     * 
     * @return o nome completo da página.
     */
    protected String getFullPageName() {
        return StringUtils.join(this.getPagePath(), BREAD_CRUMB_SEPARATOR);
    }

    /**
     * Cria uma nova instância de um {@link TextField}.
     * 
     * @param <T> tipo do model do {@link TextField}
     * @param id id
     * @return uma nova instancia de {@link TextField}
     */
    protected final <T> TextField<T> createTextField(String id) {
        return new TextField<T>(id);
    }

    /**
     * Cria uma nova instância de um {@link TextField}.
     * 
     * @param <T> tipo do model do {@link TextField}
     * @param id id
     * @param model {@link IModel}
     * @return uma nova instancia de {@link TextField}
     */
    protected final <T> TextField<T> createTextField(String id, IModel<T> model) {
        return new TextField<T>(id, model);
    }

    /**
     * Cria uma nova instância de um {@link TextField} com um model do tipo {@link PropertyModel}.
     * 
     * @param <T> tipo do model do {@link TextField}
     * @param id id
     * @param modelObject o objeto
     * @param expression expression
     * @return uma nova instancia de {@link TextField}
     */
    protected final <T> TextField<T> createTextField(String id, Object modelObject, String expression) {
        return this.createTextField(id, new PropertyModel<T>(modelObject, expression));
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param choices lista de opções que devem ser exibidas
     * @param allowEmpty permitir opção vazia
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, List<T> choices, boolean allowEmpty) {
        DropDownChoice<T> dropDownChoice = new DropDownChoice<T>(id, choices);
        dropDownChoice.setNullValid(allowEmpty);
        return dropDownChoice;
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param choices lista de opções que devem ser exibidas
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, List<T> choices) {
        return this.createDropDown(id, choices, false);
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param model {@link IModel}
     * @param choices lista de opções que devem ser exibidas
     * @param allowEmpty permitir opção vazia
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, IModel<T> model, List<T> choices, boolean allowEmpty) {
        DropDownChoice<T> dropDownChoice = new DropDownChoice<T>(id, model, choices);
        dropDownChoice.setNullValid(allowEmpty);
        return dropDownChoice;
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param model {@link IModel}
     * @param choices lista de opções que devem ser exibidas
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, IModel<T> model, List<T> choices) {
        return this.createDropDown(id, model, choices, false);
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice} com um model do tipo {@link PropertyModel}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param modelObject o objeto
     * @param expression expression da property
     * @param choices lista de opções que devem ser exibidas
     * @param allowEmpty permitir opção vazia
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, Object modelObject, String expression, List<T> choices,
            boolean allowEmpty) {
        return this.createDropDown(id, new PropertyModel<T>(modelObject, expression), choices, allowEmpty);
    }

    /**
     * Cria uma nova instância de um {@link DropDownChoice} com um model do tipo {@link PropertyModel}.
     * 
     * @param <T> tipo do model do {@link DropDownChoice}
     * @param id id
     * @param modelObject o objeto
     * @param expression expression
     * @param choices lista de opções que devem ser exibidas
     * @return uma nova instancia de {@link DropDownChoice}
     */
    protected final <T> DropDownChoice<T> createDropDown(String id, Object modelObject, String expression, List<T> choices) {
        return this.createDropDown(id, new PropertyModel<T>(modelObject, expression), choices, false);
    }

    /**
     * Cria uma nova instância de um {@link MapsWicketDateTextField}.
     * 
     * @param id id
     * @return uma nova instancia de {@link MapsWicketDateTextField}
     */
    protected final MapsWicketDateTextField createDateField(String id) {
        return MapsWicketDateTextField.forDatePattern(id);
    }

    /**
     * Cria uma nova instância de um {@link MapsWicketDateTextField}.
     * 
     * @param id id
     * @param required indica se o campo data é de preenchimento obrigatório.
     * @return uma nova instancia de {@link MapsWicketDateTextField}
     */
    protected final MapsWicketDateTextField createDateField(String id, boolean required) {
        return MapsWicketDateTextField.forDatePattern(id, null, required, true);
    }

    /**
     * Cria uma nova instância de um {@link MapsWicketDateTextField}.
     * 
     * @param id id
     * @param model {@link IModel}
     * @return uma nova instancia de {@link MapsWicketDateTextField}
     */
    protected final MapsWicketDateTextField createDateField(String id, IModel<Date> model) {
        return MapsWicketDateTextField.forDatePattern(id, model);
    }

    /**
     * Cria uma nova instância de um {@link MapsWicketDateTextField}.
     * 
     * @param id id
     * @param model {@link IModel}
     * @param required indica se o campo data é de preenchimento obrigatório.
     * @return uma nova instancia de {@link MapsWicketDateTextField}
     */
    protected final MapsWicketDateTextField createDateField(String id, IModel<Date> model, boolean required) {
        return MapsWicketDateTextField.forDatePattern(id, model, required, true);
    }

    /**
     * Cria uma nova instância de um {@link MapsWicketDateTextField} com um model do tipo {@link PropertyModel}.
     * 
     * @param id id
     * @param modelObject o objeto
     * @param expression expression
     * @return uma nova instancia de {@link MapsWicketDateTextField}
     */
    protected final MapsWicketDateTextField createDateField(String id, Object modelObject, String expression) {
        return this.createDateField(id, new PropertyModel<Date>(modelObject, expression));
    }
}
